import csv
import json
import tkinter as tk
from tkinter import filedialog, messagebox, ttk

import pandas as pd
from openpyxl import Workbook

from ..utils.logger import logger


class ResultManager:
    """结果显示管理功能"""

    def _create_result_frame(self, parent):
        """创建结果显示区域"""
        # 创建结果显示区域
        result_frame = ttk.LabelFrame(parent, text="对比结果")
        result_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

        # 创建结果树形控件
        self._create_result_tree(result_frame)

        return result_frame

    def _create_result_tree(self, parent):
        """创建结果显示树形控件"""
        # 创建表格容器
        tree_frame = ttk.Frame(parent)
        tree_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

        # 创建结果表格，设置标签列
        self.result_tree = ResultTree(
            tree_frame, show="headings", style="Centered.Treeview", main_window=self
        )

        # 创建居中显示的样式
        style = ttk.Style()
        style.configure(
            "Centered.Treeview",
            rowheight=25,  # 调整行高
        )
        style.configure(
            "Centered.Treeview.Heading",
            anchor="center",  # 列标题居中
        )
        # 设置单元格文本居中
        style.layout(
            "Centered.Treeview", [("Centered.Treeview.treearea", {"sticky": "nswe"})]
        )

        # 添加滚动条
        vsb = ttk.Scrollbar(
            tree_frame, orient="vertical", command=self.result_tree.yview
        )
        hsb = ttk.Scrollbar(
            tree_frame, orient="horizontal", command=self.result_tree.xview
        )
        self.result_tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)

        # 布局
        self.result_tree.grid(column=0, row=0, sticky="nsew")
        vsb.grid(column=1, row=0, sticky="ns")
        hsb.grid(column=0, row=1, sticky="ew")

        tree_frame.grid_columnconfigure(0, weight=1)
        tree_frame.grid_rowconfigure(0, weight=1)

    def _display_result(self, df: pd.DataFrame):
        """显示对比结果"""
        self.result_tree.display_result(df)
        logger.info("显示对比结果完成")


class ResultTree(ttk.Treeview):
    """结果树形控件"""

    def __init__(self, master, **kwargs):
        self.main_window = kwargs.pop("main_window")
        self.column_display_type = "name"  # 默认值保持为 "name"
        self.current_columns = []  # 保存当前显示的列
        self.column_display_names = {}  # 保存字段代码到显示名称的映射
        super().__init__(master, **kwargs)

        # 创建红色文本标签
        style = ttk.Style()
        style.configure("Red.Treeview", foreground="red")

    def update_column_display(self, display_type: str):
        """更新列名显示方式"""
        self.column_display_type = display_type
        if self.current_columns:  # 如果有显示的列，则更新列标题
            for col in self.current_columns:
                display_name = (
                    col
                    if display_type == "code"
                    else self.column_display_names.get(col, col)
                )
                self.heading(col, text=display_name)

    def display_result(self, df: pd.DataFrame):
        """显示对比结果"""
        # 清空现有数据
        self.delete(*self.get_children())

        # 获取所有基础字段（不带后缀的）
        base_columns = []
        self.column_display_names = {}  # 重置字段映射
        for col in df.columns:
            if col.endswith("-数据源1") or col.endswith("-数据源2"):
                base_col = col.rsplit("-", 1)[0]
                if base_col not in base_columns:
                    base_columns.append(base_col)
                    # 查找字段名称
                    for field in self.main_window.data_fields:
                        if field["code"] == base_col:
                            self.column_display_names[base_col] = field["name"]
                            break
            else:
                if col not in base_columns:
                    base_columns.append(col)
                    # 查找字段名称
                    for field in self.main_window.data_fields:
                        if field["code"] == col:
                            self.column_display_names[col] = field["name"]
                            break

        # 保存当前列
        self.current_columns = base_columns

        # 设置显示列
        self["columns"] = base_columns

        # 设置列标题和宽度
        for col in base_columns:
            # 根据显示类型选择显示名称
            display_name = (
                col
                if self.column_display_type == "code"
                else self.column_display_names.get(col, col)
            )
            self.heading(col, text=display_name, anchor="center")  # 列标题居中
            self.column(col, width=150, anchor="center")  # 列内容居中

        # 添加数据行
        for idx, row in df.iterrows():
            values = []
            tags = []  # 用于存储每行的标签

            for col in base_columns:
                col1 = f"{col}-数据源1"
                col2 = f"{col}-数据源2"

                if col1 in df.columns and col2 in df.columns:
                    # 对比字段
                    val1 = str(row[col1])
                    val2 = str(row[col2])

                    # 处理特殊值
                    val1 = "" if val1.lower() in ["nan", "<na>"] else val1
                    val2 = "" if val2.lower() in ["nan", "<na>"] else val2

                    if val1 == val2:
                        # 值相同，直接显示
                        values.append(val1)
                    else:
                        # 值不同，显示差异
                        if val1 and val2:
                            # 两边都有值
                            values.append(f"{val1}❌{val2}")
                            tags.append("red")  # 添加红色标签
                        elif val1:
                            # 只有左边有值
                            values.append(f"{val1}❌")
                            tags.append("red")  # 添加红色标签
                        elif val2:
                            # 只有右边有值
                            values.append(f"❌{val2}")
                            tags.append("red")  # 添加红色标签
                        else:
                            # 都为空
                            values.append("")
                else:
                    # ID字段或其他单列字段
                    # 先尝试获取带数据源1后缀的列
                    if col1 in df.columns:
                        val = str(row[col1])
                    # 如果不存在，则尝试获取原始列名
                    elif col in df.columns:
                        val = str(row[col])
                    # 如果都不存在，则尝试获取带数据源2后缀的列
                    elif col2 in df.columns:
                        val = str(row[col2])
                    else:
                        val = ""
                    values.append("" if val.lower() in ["nan", "<na>"] else val)

            item = self.insert("", tk.END, values=values)
            # 为包含❌的单元格设置红色标签
            for i, value in enumerate(values):
                if "❌" in str(value):
                    self.set(item, i, value)
                    self.tag_configure("red", foreground="red")
                    self.item(item, tags=("red",))

    def _on_export_result(self, file_ext):
        """导出对比结果"""
        try:
            # 获取当前显示的数据
            data = []
            headers = self["columns"]
            # 根据当前显示类型获取列名
            display_headers = [
                (
                    col
                    if self.column_display_type == "code"
                    else self.column_display_names.get(col, col)
                )
                for col in headers
            ]

            # 获取数据
            for item in self.get_children():
                values = self.item(item)["values"]
                # 使用显示列名作为字典的键
                data.append(dict(zip(display_headers, values)))

            # 根据文件扩展名选择不同的导出方式
            if file_ext == ".csv":
                self._export_to_csv(data, display_headers)
            elif file_ext == ".xlsx":
                self._export_to_excel(data, display_headers)
            elif file_ext == ".json":
                self._export_to_json(data)

            logger.info(f"导出结果成功")
            messagebox.showinfo("成功", "导出成功")

        except Exception as e:
            logger.error(f"导出结果失败: {str(e)}", exc_info=True)
            messagebox.showerror("错误", f"导出失败: {str(e)}")

    def _export_to_csv(self, data, headers):
        """导出为CSV文件"""
        file_path = filedialog.asksaveasfilename(
            defaultextension=".csv",
            filetypes=[("CSV files", "*.csv"), ("All files", "*.*")],
        )
        if file_path:
            with open(file_path, "w", newline="", encoding="utf-8") as f:
                writer = csv.DictWriter(f, fieldnames=headers)
                writer.writeheader()
                writer.writerows(data)

    def _export_to_excel(self, data, headers):
        """导出为Excel文件"""
        file_path = filedialog.asksaveasfilename(
            defaultextension=".xlsx",
            filetypes=[("Excel files", "*.xlsx"), ("All files", "*.*")],
        )
        if file_path:
            wb = Workbook()
            ws = wb.active
            # 写入表头
            ws.append(headers)
            # 写入数据
            for row in data:
                ws.append([row[header] for header in headers])
            wb.save(file_path)

    def _export_to_json(self, data):
        """导出为JSON文件"""
        file_path = filedialog.asksaveasfilename(
            defaultextension=".json",
            filetypes=[("JSON files", "*.json"), ("All files", "*.*")],
        )
        if file_path:
            with open(file_path, "w", encoding="utf-8") as f:
                json.dump(data, f, ensure_ascii=False, indent=4)
